from flask import Flask, request, redirect, url_for, flash, render_template
from flask_sqlalchemy import SQLAlchemy
from flask import Blueprint, jsonify, request, make_response, json
from flask_restful import Api, Resource, reqparse, marshal, fields
from Models import db
from Models.User import User
from Utility.tools import get_params
from datetime import datetime, timedelta
from Settings.config import Config
from Crypto.PublicKey import RSA
from Utility.tools import md5_encrypt, rsa_decrypt
from Utility.img_code import generate_captcha_image, verify_img_code
from Settings.config import Config
from Apscheduler import scheduler
from Apscheduler.task import del_file

import time
import jwt

redis_serve = Config().SESSION_REDIS

SECRET_KEY = Config().SECRET_KEY

user_blue = Blueprint("User", __name__, url_prefix='/user')


@user_blue.route('/register', methods=["POST"])
def register():  # 需加邮箱验证码或短信验证码 来 验证账号是否真实
    params = get_params(request)
    username = params.get('username', None)
    password = params.get('password', None)
    print(params)
    try:
        username = rsa_decrypt(str(username))

        password = rsa_decrypt(str(password))  # rsa解码
        print('rsa', password)
        password = md5_encrypt(password)  # md5 加密
        print('md5', password)

        user_info = db.session.query(User).filter(
            User.username == str(username)).first()  # 查询该账号用户
        if user_info:
            return {'code': 201, 'msg': f'该账号已被注册'}

        User_ = User(username=username, password=password)
        db.session.add(User_)
        db.session.commit()

        print('注册成功')
        return {'code': 200, 'msg': f'注册成功'}

    except Exception as e:

        print('注册失败')
        return {'code': 500, 'msg': f'注册失败，报错信息为{e},方法为 User_blue/register'}


@user_blue.route('/login', methods=["POST"])
def login():
    try:
        params = get_params(request)
        print(params)
        username = params.get('username')  # 获取账号
        password = params.get('password')  # 获取rsa加密后的密码
        # img_code = params.get('img_code')

        username = rsa_decrypt(str(username))  # rsa解码

        # keys = 'img_code' + str(username)
        # res = verify_img_code(keys=keys,code=img_code)
        #
        # if not res:
        #     return jsonify({'code': 201, 'msg': '验证码有误', 'data': {}})
        # else:
        #     if res == '过期':
        #         return jsonify({'code': 203, 'msg': '验证码过期', 'data': {}})

        user_info = db.session.query(User).filter(
            User.username == str(username)).first()  # 查询该账号用户

        if not user_info:
            return jsonify({'code': 900, 'msg': '用户不存在', 'data': {}})

        password = rsa_decrypt(str(password))  # rsa解码
        print('rsa', password)
        password = md5_encrypt(password)  # md5 加密
        print('md5', password)

        if user_info.password != password:
            return jsonify({'code': 900, 'msg': '密码输入错误', 'data': {}})

        if user_info.password == password:
            # 生成token userName：接收人 aud：接收人id exp：过期时间戳
            header = {'typ': 'JWT', 'alg': 'HS256'}  # 签名算法
            exp_date = datetime.now() + timedelta(
                seconds=360)
            struct_time = exp_date.timetuple()  # struct_time类型
            exp = int(time.mktime(struct_time))
            payload = {
                'aud': user_info.id,
                'userName': username,
                'pwd': password,
                'exp': exp,
            }
            token = jwt.encode(headers=header,
                               payload=payload,
                               key=SECRET_KEY)  # byte类型

            data = {'token': 'Bearer ' + token.decode()}
            return {'code': 0, 'data': data, 'msg': '登录成功'}

    except Exception as e:
        return {'code': 500, 'msg': f'方法为User/login, 报错信息为{e}'}


# 获取rsa公钥
@user_blue.route('/get_keys', methods=["GET"])
def get_keys():
    try:
        with open('RSA_keys/company_rsa_public_key.pem', 'r') as f:
            public_key = f.read()
        print(public_key)
        return {'code': 0, 'data': public_key, 'msg': '获取成功'}
    except Exception as e:
        return {'code': 500, 'msg': f'获取失败，{e}'}


@user_blue.route('/generate_rsa_keys', methods=["PUT"])
def generate_new_keys():
    try:
        # 生成密钥对
        key = RSA.generate(2048)
        # 将公钥和私钥保存到文件中
        with open('RSA_keys/company_rsa_public_key.pem', 'wb') as f:
            f.write(key.publickey().export_key())
        with open('RSA_keys/company_rsa_private_key.pem', 'wb') as f:
            f.write(key.export_key())
        return {'code': 0, 'msg': '生成rsa密钥成功'}
    except Exception as e:
        return {'code': 500, 'msg': f'生成rsa密钥失败，{e}'}


@user_blue.route('/generate_img_code', methods=["GET"])
def generate_img_code():
    try:

        params = get_params(request)

        username = params.get('username')  # 获取账号   用于当作redis的键

        keys = 'img_code' + str(username)

        path, text = generate_captcha_image()  # 生成图片验证码

        redis_serve.set(keys, text, ex=60)  # 验证码存入redis 1分钟后过期

        scheduler.add_job('del_file' + str(time.time()),  # 图片验证码2分钟后自动删除
                          del_file,
                          trigger='date',
                          run_date=datetime.now() +
                                   timedelta(seconds=120),
                          args=((path,)))

        return {'code': 0, 'msg': '生成图片验证码成功，一分钟有效哦', 'data': path}
    except Exception as e:
        return {'code': 500, 'msg': f'生成图片验证码失败，{e}'}


from Utility.RLYnote import send_message
import random


#  生成短信验证码
@user_blue.route('/generate_sms_code', methods=["GET"])
def generate_sms_code():
    try:

        params = get_params(request)

        phone = params.get('phone')

        keys = 'sms_code' + str(phone)  # 唯一键

        code = str(random.randint(1000, 9999))

        res = send_message(phone, (code, 1))  # 1分钟过期

        if res:
            redis_serve.set(keys, code, ex=60)  # 验证码存入redis 1分钟后过期

            return {'code': 0, 'msg': '发送验证码成功，注意查收'}
        else:
            return {'code': 201, 'msg': '发送验证码失败'}
    except Exception as e:
        return {'code': 500, 'msg': f'发送验证码失败，{e}'}

# http://zbb.tju.edu.cn/sfw_cms/e?page=cms.psms.gglist&typeDetail=XQ&catalog=A&cate=50133
